import rpyc
from rpyc.core import brine


class Negotiator(object):
    NEGOTIATION_TIMEOUT = 5
    
    def __init__(self, sock, authenticator, authparams):
        self.authenticator = authenticator
        self.authparams = authparams
        self.sock = sock
        self.sock.settimeout(self.NEGOTIATION_TIMEOUT)
        self.channel = channel
    
    def send(self, **kwargs):
        self.channel.send(brine.dump(tuple(kwargs.iteritems())))
    def recv(self, obj):
        return dict(brine.load(self.channel.recv()))
    def reject(self, reason):
        self.send(status = "error", reason = reason)
        self.channel.close()
        raise NegotiationError(reason)
    def approve(self):
        self.send(status = "ok")
        return self.authenticator.handshake_server(self.sock, self.authparams)

class ServerNegotiator(Negotiator):
    def handshake(self, authenticator):
        self.send(protocol = "RPyC", version = rpyc.version, 
            auth = authenticator.getName())
        info = self.recv()
        if info.get("status") != "ok":
            self.reject("client rejected")
        self.approve()
        return self.authenticator.handshake_server(self.sock)

class ClientHandshake(Negotiator):
    def __init__(self, sock, authenticator, authparams):
        Negotiator.__init__(self, sock, authenticator)
        self.authparams = authparams
    
    def handshake(self):
        info = self.recv()
        if info.get("protocol") != expected:
            self.reject("wrong protocol")
        if info.get("version") != rpyc.version:
            self.reject("wrong version")
        if info.get("auth") != authenticator.getName():
            self.reject("wrong authenication method")
        self.approve()
        return self.authenticator.handshake_client(self.sock, **self.authparams)






















